home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / patchexe.zip / PATCHEXE.PAS < prev   
Pascal/Delphi Source File  |  1990-07-12  |  7KB  |  244 lines

  1. program PatchFiles;
  2.  
  3. uses crt, dos;
  4.  
  5. const
  6.      MaxTableEntries = 1000;
  7.  
  8. type
  9.     fnstring = string[65];
  10.     rawtable = array[1..MaxTableEntries] of longint;
  11.     tabletype = ^rawtable;
  12.     ByteFile = file of byte;
  13.     CharFile = file of char;
  14.  
  15. var
  16.    verbose : boolean;
  17.  
  18.    function exist(fn:fnstring):boolean;
  19.    begin
  20.         exist := fsearch(fn, '.') <> ''
  21.    end;
  22.  
  23.    procedure Patch(var f:CharFile;
  24.                        where:longint;
  25.                        replacestring:string);
  26.    var
  27.       i:byte;
  28.    begin
  29.         writeln('Patching at ', where);
  30.         seek(f, where);
  31.         for i := 1 to length(replacestring) do
  32.             write(f, replacestring[i])
  33.    end;
  34.  
  35.    procedure SilentPatch(fname:fnstring;
  36.                          table:tabletype;
  37.                          entries:integer;
  38.                          rs:string);
  39.    var i:1..MaxTableEntries;
  40.        inf:CharFile;
  41.    begin
  42.         assign(inf, fname); reset(inf);
  43.         for i := 1 to entries do
  44.             Patch(inf, table^[i], rs);
  45.         close(inf)
  46.    end;
  47.  
  48.    function max(i,j:longint):longint;
  49.    begin
  50.         if i >= j then max := i
  51.                   else max := j
  52.    end;
  53.  
  54.    function min(i,j:longint):longint;
  55.    begin
  56.         if i <= j then min := i
  57.                   else min := j
  58.    end;
  59.  
  60.    function printable(c:char):boolean;
  61.    const
  62.         PrintableCharacters : set of char
  63.                             = [#32..#255];
  64.    begin
  65.         printable := c in PrintableCharacters
  66.    end;
  67.  
  68.    procedure Display(var f:CharFile;
  69.                      rmin, rmax, focus : longint;
  70.                      highlightlength:byte);
  71.    var i:longint;
  72.        outc, c:char;
  73.    begin
  74.         seek(f, rmin);
  75.         for i := rmin to rmax do
  76.         begin
  77.              read(f, c);
  78.              if printable(c) then outc := c
  79.                              else outc := #254;
  80.  
  81.              if (i >= focus) and (i <= (focus+highlightlength))
  82.              then textattr := 15
  83.              else textattr := 7;
  84.              write(outc)
  85.         end;
  86.    end;
  87.  
  88.    procedure InteractivePatch(fname:fnstring;
  89.                               table:tabletype;
  90.                               entries : integer;
  91.                               rs:string);
  92.    var
  93.       inf:CharFile;
  94.       rmin, rmax, UpperLimit : longint;
  95.       i : 1..MaxTableEntries;
  96.  
  97.    begin
  98.         assign(inf, fname); reset(inf);
  99.         Upperlimit := filesize(inf);
  100.         for i := 1 to entries do
  101.         begin
  102.              rmin := max (0, table^[i] - 30);
  103.              rmax := min (Upperlimit, table^[i] + 30);
  104.              Display(inf, rmin, rmax, table^[i], length(rs)-1);
  105.              writeln;
  106.              write('Replace? ');
  107.              if upcase(readkey) = 'Y' then
  108.                 Patch(inf, table^[i], rs);
  109.              writeln
  110.         end;
  111.    end;
  112.  
  113.    procedure Work(fname:fnstring;
  114.                   sstring, rstring:string;
  115.                   verbose:boolean);
  116.  
  117.    label done;
  118.  
  119.    var inf:CharFile;
  120.        entries : integer;
  121.        table : tabletype;
  122.        address : longint;
  123.        i : byte;
  124.        c : char;
  125.        destruct : boolean;
  126.  
  127.    begin
  128.         write('Searching...');
  129.         entries := 0; new(table);
  130.         assign(inf, fname); reset(inf);
  131.         repeat
  132.               repeat
  133.                     if eof(inf) then goto done;
  134.                     read(inf, c);
  135.               until c = sstring[1];
  136.               address := filepos(inf);
  137.  
  138.               {We'll now "try out" that chappie.}
  139.               destruct := false;
  140.               i := 2;
  141.               repeat
  142.                    if eof(inf) then goto done;
  143.                    read(inf, c);
  144.                    if c <> sstring[i] then destruct := true;
  145.                    inc(i);
  146.               until (i > length(sstring)) or destruct;
  147.  
  148.               if destruct
  149.                then seek(inf, address)
  150.               else {we have a occurence of searchstring}
  151.                begin
  152.                     inc(entries); write('.');
  153.                     table^[entries] := address - 1
  154.                end
  155.         until eof(inf);
  156.  
  157. done:
  158.     close(inf);
  159.     if entries = 0 then
  160.     begin
  161.          writeln('No occurences of ', sstring, ' found.');
  162.          halt(0)
  163.     end;
  164.     writeln('Finished searching.');
  165.     if verbose then InteractivePatch(fname, table, entries, rstring)
  166.                else SilentPatch(fname, table, entries, rstring)
  167.                     {talk to stdout, though}
  168.    end;
  169.  
  170.     procedure help;
  171.     const
  172.          NumStrings = 11;
  173.          Strings : array[1..NumStrings] of string
  174.                  = ('Usage:',
  175.                     '        patch [-v] filename string1 string2',
  176.                     '',
  177.                     'filename is the file which is patched.',
  178.                     'You must have length(string1) = length(string2).',
  179.                     '',
  180.                     'Without the verbose flag, every occurence of string1 is replaced by string2.',
  181.                     '',
  182.                     'With verbose on:',
  183.                     'Every occurence of string1 is displayed on screen, along with it''s context.',
  184.                     'Iff you give a goahead, then the patch is made.');
  185.     var i:byte;
  186.     begin
  187.          for i := 1 to NumStrings do writeln(Strings[i]);
  188.          halt(1)
  189.     end;
  190.  
  191.     procedure courtesy;
  192.     begin
  193.          writeln('Say');
  194.          writeln('      patch');
  195.          writeln('for more help.');
  196.          halt(1)
  197.     end;
  198.  
  199. var
  200.    firstparam : string;
  201.    filename : fnstring;
  202.    searchstring, replacestring : string;
  203.    
  204.    i : byte;
  205.  
  206. begin
  207.      if (paramcount = 0) or (paramcount > 4) then help;
  208.      verbose := false;
  209.      firstparam := paramstr(1);
  210.      if firstparam[1] = '-' then {might have a -v here}
  211.      begin
  212.           if upcase(firstparam[2]) = 'V'
  213.              then verbose := true
  214.              else help;
  215.           filename := paramstr(2);
  216.           searchstring := paramstr(3);
  217.           replacestring := paramstr(4);
  218.  
  219.      end
  220.      else {first parameter isn't -*}
  221.      begin
  222.           filename := paramstr(1);
  223.           searchstring := paramstr(2);
  224.           replacestring := paramstr(3)
  225.      end;
  226.  
  227.      if length(searchstring) <> length(replacestring) then
  228.      begin
  229.           writeln('Searchstring and Replacestring must be of same length.');
  230.           courtesy
  231.      end;
  232.      if length(searchstring) = 0 then
  233.      begin
  234.           writeln('You have to specify some searchstring.'); courtesy
  235.      end;
  236.      if not exist(filename) then
  237.      begin
  238.           writeln('File ', filename, ' not found.'); courtesy
  239.      end;
  240.  
  241.      {Now we have all the raw materials only.}
  242.      Work(filename, searchstring, replacestring, verbose)
  243. end.
  244.